#include "StdAfx.h"

MomentumWave::MomentumWave(Symbol ^owner, MomentumWaveOptions ^options, float delta, int steps, float triggerPrice, float stopLossPrice, Side side) : StrategyAbstract(owner, options)
{
	this->delta = delta;
	this->steps = steps;
	this->triggerPrice = triggerPrice;
	this->stopLossPrice = stopLossPrice;
	this->side = side;

	curStep = 1;
	abovePrice = triggerPrice + delta;
	belowPrice = triggerPrice - delta;
	if (side == Long) profit1_Price = triggerPrice + (delta * options->profit1_Destination);
	if (side == Short) profit1_Price = triggerPrice - (delta * options->profit1_Destination);
	if (side == Long) profit2_Price = triggerPrice + (delta * options->profit2_Destination);
	if (side == Short) profit2_Price = triggerPrice - (delta * options->profit2_Destination);

	aboveStepOrderID = -1;
	belowStepOrderID = -1;
	limit1_OrderID = -1;
	limit2_IsActivated = false;
	triggerOrderQuantity = aboveOrderQuantity = belowOrderQuantity = limit1_OrderQuantity = 0;

	triggerOrderID = owner->Orders_()->NewOrder(options->firstQuantity, side, OrderTypes::Limit, 0, triggerPrice, true);
	triggerActivated = false;
	owner->MarketData_()->Start();
}

void MomentumWave::HistoryBarsCompleted()
{

}

void MomentumWave::NewBarAdded( Bar ^barInformation )
{

}

void MomentumWave::NewMarketData( MarketDataTypes whatChanged, float price )
{

}

void MomentumWave::OrderStatusChanged( int orderIndex, OrderData ^orderData, bool firstTimeThatGotQuantity )
{
	// Trigger Code
	if (orderIndex == triggerOrderID)
	{
		if (side == Long)
			if (firstTimeThatGotQuantity == true)
			{
				belowStepOrderID = owner->Orders_()->NewOrder(((MomentumWaveOptions^)strategyOptions)->quantityToAdd, Long, Limit, 0, belowPrice, true);
				limit1_OrderID = owner->Orders_()->NewOrder(owner->Orders_()->AllFilledQuantity(), Short, Limit, 0, profit1_Price, false);
				owner->Account_()->AddToLog(owner->Name(), "Limit 1 at " + Convert::ToString(profit1_Price) + ", Add Quantity at " + Convert::ToString(belowPrice));
			}
			else if (firstTimeThatGotQuantity == false && orderData->FilledQuantity() != 0)
			{
				owner->Orders_()->UpdateOrder(limit1_OrderID, owner->Orders_()->AllFilledQuantity(), Short, Limit, 0, profit1_Price, false);
				//owner->Account_()->AddToLog(owner->Name(), "Updated: Limit 1 at " + Convert::ToString(profit1_Price) + ", Add Quantity at " + Convert::ToString(belowPrice));
			}

		if (side == Short)
			if (firstTimeThatGotQuantity == true)
			{
				aboveStepOrderID = owner->Orders_()->NewOrder(((MomentumWaveOptions^)strategyOptions)->quantityToAdd, Short, Limit, 0, abovePrice, true);
				limit1_OrderID = owner->Orders_()->NewOrder(owner->Orders_()->AllFilledQuantity(), Long, Limit, 0, profit1_Price, false);
				owner->Account_()->AddToLog(owner->Name(), "Limit 1 at " + Convert::ToString(profit1_Price) + ", Add Quantity at " + Convert::ToString(abovePrice));
			}
			else if (firstTimeThatGotQuantity == false && orderData->FilledQuantity() != 0)
			{
				owner->Orders_()->UpdateOrder(limit1_OrderID, owner->Orders_()->AllFilledQuantity(), Long, Limit, 0, profit1_Price, false);
				//owner->Account_()->AddToLog(owner->Name(), "Update: Limit 1 at " + Convert::ToString(profit1_Price) + ", Add Quantity at " + Convert::ToString(abovePrice));
			}
	}

	// Below Step Code
	if (orderIndex == belowStepOrderID  && firstTimeThatGotQuantity == true)
	{
		if (side == Long)
		{
			if (curStep == 1)
			{
				owner->Orders_()[limit1_OrderID]->CancelLimit();
				owner->Account_()->AddToLog(owner->Name(), "Reach below step, closed limit 1 order");
			}
			else
			{
				owner->Orders_()[aboveStepOrderID]->CancelLimit();
				owner->Account_()->AddToLog(owner->Name(), "Reach below step, closed above step order");
			}

			if (curStep == steps)
			{
				owner->Orders_()->CancelLimitsAndSellQuantity(belowPrice);
				owner->Account_()->AddToLog(owner->Name(), "Reach Stop Loss! Close the position with limit order");
				curStep++;
				return;
			}

			curStep++;
			abovePrice = belowPrice + delta;
			belowPrice = belowPrice - delta;

			belowStepOrderID = owner->Orders_()->NewOrder(((MomentumWaveOptions^)strategyOptions)->quantityToAdd, Long, Limit, 0, belowPrice, true);
			aboveStepOrderID = owner->Orders_()->NewOrder(((MomentumWaveOptions^)strategyOptions)->quantityToAdd, Short, Limit, 0, abovePrice, true);
			owner->Account_()->AddToLog(owner->Name(), "Above step at " + Convert::ToString(abovePrice) + ", Add Quantity at " + Convert::ToString(belowPrice));
		}

		if (side == Short)
		{
			if (curStep != steps + 1)
			{
				owner->Orders_()[aboveStepOrderID]->CancelLimit();
				owner->Account_()->AddToLog(owner->Name(), "Reach below step, closed above step order");
			}

			if (curStep == 2)
			{
				limit1_OrderID = owner->Orders_()->NewOrder(owner->Orders_()->AllFilledQuantity(), Long, Limit, 0, profit1_Price, false);
				abovePrice = belowPrice;
				aboveStepOrderID = owner->Orders_()->NewOrder(((MomentumWaveOptions^)strategyOptions)->quantityToAdd, Short, Limit, 0, abovePrice, true);
				owner->Account_()->AddToLog(owner->Name(), "Limit 1 at " + Convert::ToString(profit1_Price) + ", Add Quantity at " + Convert::ToString(abovePrice));
				curStep--;
				return;
			}

			curStep--;
			belowPrice = belowPrice - delta;
			abovePrice = belowPrice + delta;

			belowStepOrderID = owner->Orders_()->NewOrder(((MomentumWaveOptions^)strategyOptions)->quantityToAdd, Long, Limit, 0, belowPrice, true);
			aboveStepOrderID = owner->Orders_()->NewOrder(((MomentumWaveOptions^)strategyOptions)->quantityToAdd, Short, Limit, 0, abovePrice, true);
			owner->Account_()->AddToLog(owner->Name(), "Below step at " + Convert::ToString(belowPrice) + ", Add Quantity at " + Convert::ToString(abovePrice));
		}
	}

	// Above Step Code
	if (orderIndex == aboveStepOrderID && firstTimeThatGotQuantity == true)
	{
		if (side == Long)
		{
			if (curStep != steps + 1)
			{
				owner->Orders_()[belowStepOrderID]->CancelLimit();
				owner->Account_()->AddToLog(owner->Name(), "Reach above step, closed below step order");
			}

			if (curStep == 2)
			{
				belowPrice = abovePrice - delta;
				belowStepOrderID = owner->Orders_()->NewOrder(((MomentumWaveOptions^)strategyOptions)->quantityToAdd, Long, Limit, 0, belowPrice, true);
				limit1_OrderID = owner->Orders_()->NewOrder(owner->Orders_()->AllFilledQuantity(), Short, Limit, 0, profit1_Price, false);
				owner->Account_()->AddToLog(owner->Name(), "Limit 1 at " + Convert::ToString(profit1_Price) + ", Add Quantity at " + Convert::ToString(belowPrice));
				curStep--;
				return;
			}

			curStep--;
			belowPrice = abovePrice - delta;
			abovePrice = abovePrice + delta;

			belowStepOrderID = owner->Orders_()->NewOrder(((MomentumWaveOptions^)strategyOptions)->quantityToAdd, Long, Limit, 0, belowPrice, true);
			aboveStepOrderID = owner->Orders_()->NewOrder(((MomentumWaveOptions^)strategyOptions)->quantityToAdd, Short, Limit, 0, abovePrice, true);
			owner->Account_()->AddToLog(owner->Name(), "Above step at " + Convert::ToString(abovePrice) + ", Add Quantity at " + Convert::ToString(belowPrice));
		}

		if (side == Short)
		{
			if (curStep == 1)
			{
				owner->Orders_()[limit1_OrderID]->CancelLimit();
				owner->Account_()->AddToLog(owner->Name(), "Reach above step, closed limit 1 order");
			}
			else
			{
				owner->Orders_()[belowStepOrderID]->CancelLimit();
				owner->Account_()->AddToLog(owner->Name(), "Reach above step, closed below step order");
			}

			if (curStep == steps)
			{
				owner->Orders_()->CancelLimitsAndSellQuantity(abovePrice);
				owner->Account_()->AddToLog(owner->Name(), "Reach Stop Loss! Close the position with limit order");
				curStep++;
				return;
			}

			curStep++;
			abovePrice = abovePrice + delta;
			belowPrice = abovePrice - delta;

			belowStepOrderID = owner->Orders_()->NewOrder(((MomentumWaveOptions^)strategyOptions)->quantityToAdd, Long , Limit, 0, belowPrice, true);
			aboveStepOrderID = owner->Orders_()->NewOrder(((MomentumWaveOptions^)strategyOptions)->quantityToAdd, Short , Limit, 0, abovePrice, true);
			owner->Account_()->AddToLog(owner->Name(), "Below step at " + Convert::ToString(belowPrice) + ", Add Quantity at " + Convert::ToString(abovePrice));
		}
	}

	// Limit 1 Code
	if (orderIndex == limit1_OrderID && firstTimeThatGotQuantity == true)
	{
		if (side == Long)
			owner->Orders_()[belowStepOrderID]->CancelLimit();

		if (side == Short)
			owner->Orders_()[aboveStepOrderID]->CancelLimit();

		owner->Account_()->AddToLog(owner->Name(), "Reach Limit 1!");
	}
}

// ****************************************************************************************************

void MomentumWaveOptions::SetToDefault()
{
	profit1_Destination = 1.5;
	profit2_Destination = 3;
	profit1_Proportion = mwHalf;
	profit2_Proportion = mwHalf;
	riskInDollar = 50;
	firstQuantity = 100;
	quantityToAdd = 50;
}

MomentumWaveOptions^ MomentumWaveOptions::Clone()
{
	MomentumWaveOptions ^newObj = gcnew MomentumWaveOptions();

	newObj->firstQuantity = this->firstQuantity;
	newObj->profit1_Destination = this->profit1_Destination;
	newObj->profit1_Proportion = this->profit1_Proportion;
	newObj->profit2_Destination = this->profit2_Destination;
	newObj->profit2_Proportion = this->profit2_Proportion;
	newObj->quantityToAdd = this->quantityToAdd;
	newObj->riskInDollar = this->riskInDollar;

	return newObj;
}
